package com.service.sys.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.Const;
import com.common.Result;
import com.config.globalException.BusinessException;
import com.config.security.JwtTokenUtil;
import com.entity.sys.Role;
import com.entity.sys.User;
import com.mapper.sys.*;
import com.service.sys.UserService;
import com.utils.RedisUtil;
import com.vo.sys.UserLoginParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author clay
 * @since 2022-02-15
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private UserDetailsService userDetailsService;

    @Autowired
    //加密方式
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Resource
    private UserMapper userMapper;

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private MenuRoleMapper menuRoleMapper;

    @Resource
    private MenuMapper menuMapper;

    public static void main(String[] args) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encode = bCryptPasswordEncoder.encode("123456");
        //对密码进行加密操作
        System.out.println(encode);
        //校验密码是否和数据库的相等
        System.out.println(bCryptPasswordEncoder.matches("123456", "$2a$10$OmPeNmbrg5dQ62TzZ1JBXOqYeFX3w.KChzmwvQR47G57d9JfYYTxW"));
    }

    @Override
    public Result login(UserLoginParam userLoginParam, HttpServletRequest request) {
        log.info("登录信息:{}", JSON.toJSON(userLoginParam));
        //校验验证码
        System.out.println("userLoginParam.getCodeKey() = " + userLoginParam.getCodeKey());
        System.out.println("userLoginParam.getCaptchaImg() = " + userLoginParam.getCaptchaImg());
        validateCaptcha(userLoginParam.getCodeKey(), userLoginParam.getCaptchaImg());
        String username = userLoginParam.getUsername();
        String password = userLoginParam.getPassword();
        System.out.println("username = " + username);
        System.out.println("password = " + password);

        //登录功能
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        System.out.println("查出用户:" + JSON.toJSON(userDetails));

        //测试关闭密码校验
        if (Objects.isNull(userDetails) || !passwordEncoder.matches(password, userDetails.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }
        if (!userDetails.isEnabled()) {
            throw new BusinessException("账号被禁用");
        }

        //更新security登录用户对象
        UsernamePasswordAuthenticationToken userToken = new UsernamePasswordAuthenticationToken(
                //用户详情, 密码（一般不放在token, 不安全）, 权限列表
                userDetails, null, userDetails.getAuthorities()
        );
        //通过security更新用户对象
        SecurityContextHolder.getContext().setAuthentication(userToken);
        //修改用户最后登录信息
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        userMapper.updateLastLoginTimeByUserName(simpleDateFormat.format(new Date()), userDetails.getUsername());
        //生成token
        String token = jwtTokenUtil.generateToken(userDetails);
        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("token", token);
        tokenMap.put("tokenHead", tokenHead);
        return Result.success("登录成功", tokenMap);
    }

    @Override
    public User getUserByUsername(String username) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq(
                "username", username
        ));
        if (Objects.isNull(user)) {
            throw new BusinessException("用户名错误");
        }
        if (!user.getEnable()) {
            throw new BusinessException("用户被禁用, 请联系管理员");
        }
        return user;
    }


    @Override
    public List<Role> getRoles(String userId) {
        System.out.println("用户id" + userId);
        List<Role> roles = roleMapper.getRoles(userId);
        System.out.println("通过id查询到权限，" + JSON.toJSONString(roles));
        return roles;
    }

    @Override
    public User getUserByPrimary(String id) {
        return this.getById(id);
    }

    @Override
    public Boolean addUser(User user) {
        //校验用户名、手机号、身份证号是否存在
        QueryWrapper<User> wra = new QueryWrapper<User>().eq(
                "username", user.getUsername()
        ).or().eq(
                "phone", user.getPhone()
        ).or().eq(
                "nbr", user.getNbr()
        );
        List<User> list = this.list(wra);
        if (list.size() > 0) {
            throw new BusinessException("用户名、电话、证件号码可能重复, 请检查!");
        }


        //设置初始密码
        user.setPassword(passwordEncoder.encode("123456"));
        return this.save(user);
    }

    @Override
    public List<User> selectUser(User user) {
        QueryWrapper<User> wrapper = new QueryWrapper<User>().eq(
                !StringUtils.isEmpty(user.getUsername()),
                "username", user.getUsername()
        ).eq(
                !StringUtils.isEmpty(user.getDepartmentId()),
                "department_id", user.getDepartmentId()
        ).eq(
                !StringUtils.isEmpty(user.getNbr()),
                "nbr", user.getNbr()
        );
        List<User> users = this.list(wrapper);
        for (User user1 : users) {
            user1.setRoles(this.getRoles(user1.getId()));
        }
        return users;
    }

    @Override
    public Boolean resetPassword(String id) {
        String password = passwordEncoder.encode("123456");
        return userMapper.resetPassword(password, id);
    }


    /**
     * 校验验证码是否正确
     *
     * @param codeKey
     * @param captchaImg
     */
    private void validateCaptcha(String codeKey, String captchaImg) {
        System.out.println("codeKey:" + codeKey + ";captchaImg:" + captchaImg);
        System.out.println("Redis: captchaImg:" + redisUtil.hget(Const.CAPTCHA_KEY, codeKey));
        if (StringUtils.isEmpty(codeKey) || StringUtils.isEmpty(captchaImg)) {
            throw new BusinessException("验证码错误!");
        }

        if (!captchaImg.equals(redisUtil.hget(Const.CAPTCHA_KEY, codeKey))) {
            throw new BusinessException("验证码错误!");
        }
        //一次性使用, 需要删除
        redisUtil.hdel(Const.CAPTCHA_KEY, codeKey);
    }



}

